package ldk.util.slipview

import android.app.Activity
import android.app.Application
import android.os.Bundle
import android.util.Log
import android.util.SparseArray
import android.util.SparseBooleanArray

/**
 * The Activity lifecycle for recording activity task
 * All methods called from main thread
 * Created by ke on 17-6-26.
 */
open class ApplicationSingleTask: Application.ActivityLifecycleCallbacks {
    val TAG = "ApplicationSingleTask"
    val INDEX = "SingleTask_Index"

    /**
     * Don't export mIndex2Activities to public
     * if you want to add function to this object, like previousActivity(), currentActivity()
     * please request me!! or extends this object
     */
    protected val mIndex2Activities = SparseArray<Activity>()
    private val mIndex2HasSaveState = SparseBooleanArray()
    private var mLargestIndex = -1

    private val mDestroyedActivity = Activity()
    private var mCurrentVisibleActivity: Activity? = null


    /**
     * clear this task
     * @param excludeCurrentActivity is exclude current activity, default is false
     */
    fun clearTask(excludeCurrentActivity: Boolean = false){
        mIndex2HasSaveState.clear()
        mIndex2Activities.clear()
        mLargestIndex = -1
        if (excludeCurrentActivity && mCurrentVisibleActivity != null){
            mLargestIndex = 0
            mIndex2Activities.put(mLargestIndex, mCurrentVisibleActivity)
        }else{
            mCurrentVisibleActivity = null
        }
    }

    fun currentActivity(): Activity?{
        return if (mCurrentVisibleActivity != null){
            mCurrentVisibleActivity
        }else{
            mIndex2Activities.get(mLargestIndex)
        }
    }

    fun isInFront(): Boolean{
        return mCurrentVisibleActivity != null
    }


    fun previousActivity(containDestroyed: Boolean): Activity?{
        if (mLargestIndex < 1) return null

        val currentIndex: Int
        if (mCurrentVisibleActivity != null){
            val index = mIndex2Activities.indexOfValue(mCurrentVisibleActivity)
            if (index == -1) return null
            currentIndex = mIndex2Activities.keyAt(index)
            mLargestIndex = currentIndex
        }else{
            currentIndex = mLargestIndex
        }

        for (index in currentIndex - 1 downTo 0){
            val activity = mIndex2Activities.get(index) ?: continue
            if (activity == mDestroyedActivity){
                Log.e(TAG, "previous was destroyed by system, and not restored")
                if (containDestroyed) return null
                else continue
            }
            return activity
        }
        return null
    }

    fun previousActivity(): Activity?{
        return previousActivity(true)
    }

    override fun onActivityPaused(activity: Activity?) {
        if (SlipView.DEBUG){
            Log.v(TAG, "onActivityPaused, ${activity?.componentName}")
        }
    }

    override fun onActivityResumed(activity: Activity?) {
        if (SlipView.DEBUG){
            Log.v(TAG, "onActivityResumed, ${activity?.componentName}")
        }
        mCurrentVisibleActivity = activity
        val index = keyOfValue(activity!!)
        if (index != -1){
            mIndex2HasSaveState.delete(index)
            mLargestIndex = index
        }
    }

    override fun onActivityStarted(activity: Activity?) {
        if (SlipView.DEBUG){
            Log.v(TAG, "onActivityStarted, ${activity?.componentName}")
        }
    }

    override fun onActivityDestroyed(activity: Activity?) {
        val index = keyOfValue(activity!!)
        if (index == -1){
            Log.v(TAG, "onActivityDestroyed, and index is -1")
            return
        }
        val hasSavedState = mIndex2HasSaveState.get(index)
        if (SlipView.DEBUG){
            Log.v(TAG, "onActivityDestroyed, ${activity?.componentName}, and hasSavedState $hasSavedState")
        }
        if (hasSavedState){
            mIndex2Activities.put(index, mDestroyedActivity)
        }else{
            // clear state and rest index
            if (index == mLargestIndex){
                mLargestIndex -= 1
            }
            mIndex2HasSaveState.delete(index)
            mIndex2Activities.delete(index)
        }
    }

    override fun onActivitySaveInstanceState(activity: Activity?, outState: Bundle?) {
        if (SlipView.DEBUG){
            Log.v(TAG, "onActivitySaveInstanceState, ${activity?.componentName}")
        }
        val index = keyOfValue(activity!!)
        if (index == -1) return
        outState!!.putInt(INDEX, index)
        mIndex2HasSaveState.put(index, true)
    }

    private fun keyOfValue(activity: Activity): Int {
        var index = mIndex2Activities.indexOfValue(activity)
        if (index == -1) {
            Log.d(TAG, "currentList: $mIndex2Activities")
            return -1
        }
        index = mIndex2Activities.keyAt(index)
        return index
    }

    override fun onActivityStopped(activity: Activity?) {
        if (SlipView.DEBUG){
            Log.v(TAG, "onActivityStopped, ${activity?.componentName}")
        }
        if (activity == mCurrentVisibleActivity) mCurrentVisibleActivity = null
    }

    override fun onActivityCreated(activity: Activity?, savedInstanceState: Bundle?) {
        if (SlipView.DEBUG){
            Log.v(TAG, "onActivityCreated, ${activity?.componentName}， $savedInstanceState")
        }
        val index =
                if(savedInstanceState != null){
                    savedInstanceState.getInt(INDEX)
                } else {
                    mLargestIndex += 1
                    mLargestIndex
                }
        mIndex2Activities.put(index, activity)
    }
}